Python的Thread基础

2026-01-01

"并发编程中的基本工具"


进程和线程

当我们在编写计算机程序的时候,我们实际上是在编写指令代码(instructions),对于操作系统而言,只有指令代码这种文本是无法执行程序的,操作系统还需要给程序分配资源(CPU、内存、网络),操作系统还需要决定进程的权限,所以可以把进程看作是一种资源容器,一种对于运行程序的抽象,一个进程就是一个正在执行程序的实例。

进程提供了不同应用之间的资源隔离,那么线程则可以当作是在一个应用中实现某种更加轻量级的进程(有时候,线程会被称作轻量级进程),一个进程内的多个线程是可以共享内存资源,分享数据和通信的成本要比进程低很多,进程更像是资源容器,而线程才是真正被 CPU 调度的基本单元,负责执行用户编写的指令。

一般在大多数生产应用中,一个进程会存在多个线程,这样做的原因是 CPU 和外部设备或任务之间,存在巨大的性能差距。考虑到一个和会和外部磁盘交互的字处理软件,如果是单线程模型的话,那么用户点击了某个处理文本文件的按钮后,整个应用就会阻塞,阻塞于对于磁盘的系统调用,用户这时候无法再使用应用的其他功能,只能等待阻塞调用的完成。

现在考虑另一个例子,一个最简单的 Web 服务器,负责把服务器上的文本文件通过 Web 协议发送给发起请求的客户端。

单线程,就像上面所说的,在读取文件时是阻塞的,也就是说多个客户端发起请求,将按照顺序一个一个处理,这样的编程模型最简单,但没有并发性。

多线程,则可以委派读取文件这一操作给多个线程,这样多个客户端发起请求,可以实现并发性读取。

如果读取文件这一系统函数存在非阻塞的版本,那么还有一种性能更好的方式,但同时编程复杂度也最大,那就是有限状态机,这种方式可以在单线程中实现非常高的性能,对于调用是非阻塞的情况下,Web 服务器的任务可以抽象成两个事件,处理客户端请求,读取系统文件,所以多个客户端并发性的读取文件,单线程只需要调用非阻塞函数,并且将当前状态记录到表格中,立马就可以切换到下一个事件,表格中的事件,一旦完成可以通过信号或者中断的方式同时线程去处理。

这三种方式的终极目的就是在并发场景下,让系统的效率尽可能的提高,这就要求协调高速的 CPU 和缓慢的外部设备,让 CPU 尽可能的减少空转(阻塞调用)。


Python 的线程


线程的生命周期


创建线程的两种方法


线程的属性和配置项


参考

  1. https://superfastpython.com/threading-in-python/
  2. https://superfastpython.com/thread-vs-process/